package com.carter.springframework.beans.factory.annotation;

import cn.hutool.core.bean.BeanUtil;
import com.carter.springframework.beans.exception.BeanException;
import com.carter.springframework.beans.factory.BeanFactory;
import com.carter.springframework.beans.factory.BeanFactoryAware;
import com.carter.springframework.beans.factory.ConfigurableListableBeanFactory;
import com.carter.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import com.carter.springframework.beans.factory.config.PropertyValues;
import com.carter.springframework.context.annotation.Autowired;
import com.carter.springframework.context.annotation.Qualifier;
import com.carter.springframework.context.annotation.Value;
import com.carter.springframework.util.ClassUtils;

import java.lang.reflect.Field;

public class AutowiredAnnotationBeanPostProcessor implements InstantiationAwareBeanPostProcessor, BeanFactoryAware {
    private ConfigurableListableBeanFactory beanFactory;

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeanException {
        this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeanException {
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeanException {
        return bean;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeanException {
        return true;
    }

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeanException {
        return null;
    }

    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, Object bean, String beanName) throws BeanException {
        Class<?> clazz = bean.getClass();
        clazz = ClassUtils.isClibProxyClass(clazz) ? clazz.getSuperclass() : clazz;
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            resolveValueAnnotation(bean, field);
            resolveAutowiredAnnotation(bean, field);
        }
        return null;
    }

    private void resolveAutowiredAnnotation(Object bean, Field field) {
        Autowired autowiredAnnotation = field.getAnnotation(Autowired.class);
        if (autowiredAnnotation!=null){
            Class<?> fieldType = field.getType();
            String dependBeanName;
            Qualifier qualifierAnnotation = field.getAnnotation(Qualifier.class);
            Object dependBean;
            if (qualifierAnnotation!=null){
                dependBeanName = qualifierAnnotation.value();
                dependBean = beanFactory.getBean(dependBeanName, fieldType);
            }else {
                dependBean = beanFactory.getBean(fieldType);
            }
            BeanUtil.setFieldValue(bean,field.getName(),dependBean);
        }
    }

    /**
     * 处理value注解
     *
     * @param bean
     * @param field
     */
    private void resolveValueAnnotation(Object bean, Field field) {
        Value valueAnnotation = field.getAnnotation(Value.class);
        if (valueAnnotation != null) {
            String value = valueAnnotation.value();
            value = beanFactory.resolveEmbeddedValue(value);
            BeanUtil.setFieldValue(bean,field.getName(),value);
        }
    }
}
